{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Introduction"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "From v2.8.0, pymatgen comes with a fairly robust system of managing units. In essence, subclasses of float and numpy array is provided to attach units to any quantity, as well as provide for conversions. These are loaded at the root level of pymatgen and some properties (e.g., atomic masses, final energies) are returned with attached units. This demo provides an outline of some of the capabilities."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's start with some common units, like Energy."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1000.0 Ha = 27211.383859999998 eV\n",
      "Supported energy units are ('kJ', 'J', 'eV', 'Ha', 'Ry')\n"
     ]
    }
   ],
   "source": [
    "import pymatgen as mg\n",
    "#The constructor is simply the value + a string unit.\n",
    "e = mg.Energy(1000, \"Ha\")\n",
    "#Let's perform a conversion. Note that when printing, the units are printed as well.\n",
    "print \"{} = {}\".format(e, e.to(\"eV\"))\n",
    "#To check what units are supported\n",
    "print \"Supported energy units are {}\".format(e.supported_units)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Units support all functionality that is supported by floats. Unit combinations are automatically taken care of."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The speed is 2.1666666666666665 mile min^-1\n",
      "The speed is 130.0 mile h^-1\n"
     ]
    }
   ],
   "source": [
    "dist = mg.Length(65, \"mile\")\n",
    "time = mg.Time(30, \"min\")\n",
    "speed = dist / time\n",
    "print \"The speed is {}\".format(speed)\n",
    "#Let's do a more sensible unit.\n",
    "print \"The speed is {}\".format(speed.to(\"mile h^-1\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that complex units are specified as **space-separated powers of units**. Powers are specified using \"^\". E.g., \"kg m s^-1\". Only **integer powers** are supported."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, let's do some basic science."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The force is 19.62 N\n",
      "The potential energy is force is 196.20000000000002 J\n"
     ]
    }
   ],
   "source": [
    "g = mg.FloatWithUnit(9.81, \"m s^-2\") #Acceleration due to gravity\n",
    "m = mg.Mass(2, \"kg\")\n",
    "h = mg.Length(10, \"m\")\n",
    "print \"The force is {}\".format(m * g)\n",
    "print \"The potential energy is force is {}\".format((m * g * h).to(\"J\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Some highly complex conversions are possible with this system. Let's do some made up units. We will also demonstrate pymatgen's internal unit consistency checks."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2.959243823351516e-50 J^3 ang^-2\n"
     ]
    }
   ],
   "source": [
    "made_up = mg.FloatWithUnit(100, \"Ha^3 bohr^-2\")\n",
    "print made_up.to(\"J^3 ang^-2\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Units are not compatible!\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    made_up.to(\"J^2\")\n",
    "except mg.UnitError as ex:\n",
    "    print ex"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For arrays, we have the equivalent EnergyArray, ... and ArrayWithUnit classes. All other functionality remain the same."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Speeds are [  9.09090909  16.66666667  13.04347826] mile h^-1\n"
     ]
    }
   ],
   "source": [
    "dists = mg.LengthArray([1, 2, 3], \"mile\")\n",
    "times = mg.TimeArray([0.11, 0.12, 0.23], \"h\")\n",
    "print \"Speeds are {}\".format(dists / times)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## This concludes the tutorial on units in pymatgen."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
